package si.banst.tecajnice.storitve.tecajnicestoritev;

import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.logging.Logger;

import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import si.banst.tecajnice.ejb.TecajniceBeanRemote;
import si.banst.tecajnice.ejb.ValuteBeanRemote;
import si.banst.tecajnice.entitete.Tecaj;
import si.banst.tecajnice.entitete.TecajID;
import si.banst.tecajnice.entitete.Valuta;
import si.banst.tecajnice.entitete.VrstaTecajnice;
import si.banst.tecajnice.storitve.DrzavaType;
import si.banst.tecajnice.storitve.TecajType;
import si.banst.tecajnice.storitve.TecajnicaType;
import si.banst.tecajnice.storitve.ValutaType;
import si.banst.tecajnice.storitve.VrstaTecajniceType;
import si.banst.tecajnice.storitve.tecajnicestoritev.NapakaType.NapakaPriPovprasevanju;
import si.banst.tecajnice.util.DateUtil;

@RolesAllowed({ "OdgovorniReferent", "ReferentZaPreracun", "Referent", "PoslovniPartnerji" })
@javax.jws.WebService(endpointInterface = "si.banst.tecajnice.storitve.tecajnicestoritev.TecajniceStoritev", targetNamespace = "http://tecajnice.banst.si/storitve/TecajniceStoritev/", serviceName = "TecajniceStoritev", portName = "TecajniceStoritevSOAP")
public class TecajniceStoritevSOAPImpl {

	private static final Logger logger = Logger
			.getLogger(TecajniceStoritevSOAPImpl.class.getName());

	@EJB(lookup="corbaname:iiop:tecajnice.banst.si:2811#ValuteBean")
	private ValuteBeanRemote valuteBean;

	@EJB(lookup="corbaname:iiop:tecajnice.banst.si:2811#TecajniceBean")
	private TecajniceBeanRemote tecajniceBean;

	public VrniTecajniceRezultat vrniTecajnice(VrniTecajniceZahteva parameters)
			throws VrniTecajniceNapaka {

		logger.fine("Zacenjam pripravo odziva operacije vrniTecajnice. ");

		try {
			VrniTecajniceRezultat rezultat = new VrniTecajniceRezultat();

			logger.fine("Zacenjam pripravo datumov. ");
			List<Date> izbraniDatumi = new ArrayList<Date>();
			if (parameters.getDatumi() == null) {
				logger.severe("Datumi so null. ");
				throw new Exception("Datumi so null. ");
			} else {
				if (parameters.getDatumi().getDatum().isEmpty()) {
					if (parameters.getDatumi().datumOd != null) {
						GregorianCalendar gregorianCalendarDo = null;
						if (parameters.getDatumi().datumDo == null) {
							GregorianCalendar gregorianCalendar = new GregorianCalendar();
							gregorianCalendar.setTime(new Date());
							gregorianCalendarDo = gregorianCalendar;
						} else
							gregorianCalendarDo = parameters.getDatumi().datumDo
									.toGregorianCalendar();

						GregorianCalendar datumOd = parameters.getDatumi().datumOd
								.toGregorianCalendar();

						while (datumOd.before(gregorianCalendarDo)) {
							izbraniDatumi.add(DateUtil
									.nastaviCasNaPolnoc(datumOd.getTime()));
							datumOd.add(GregorianCalendar.DATE, 1);
						}

					}
				} else {
					for (XMLGregorianCalendar xmlGregorianCalendar : parameters
							.getDatumi().getDatum())
						izbraniDatumi.add(DateUtil
								.nastaviCasNaPolnoc(xmlGregorianCalendar
										.toGregorianCalendar().getTime()));
				}
			}

			List<VrstaTecajnice> vseVrsteTecajnic = tecajniceBean
					.vrniVseVrsteTecajnic();
			List<VrstaTecajnice> izbraneVrsteTecajnic = new ArrayList<VrstaTecajnice>();
			logger.fine("Zacenjam pripravo vrst tecajnic. ");
			if (parameters.getVrsteTecajnic() == null) {
				logger.fine("Vrste tecajnice so null. ");
				izbraneVrsteTecajnic = vseVrsteTecajnic;
			} else
				for (VrstaTecajnice vt : vseVrsteTecajnic)
					for (Integer sifra : parameters.getVrsteTecajnic()
							.getSifraVrsteTecajnice())
						if (vt.getSifraVrsteTecajnice() == sifra)
							izbraneVrsteTecajnic.add(vt);

			logger.fine("Zacenjam pripravo valut. ");
			List<Valuta> izbraneValute = new ArrayList<Valuta>();
			List<Valuta> vseValute = valuteBean.vrniVseValute();
			if (parameters.getValute() == null) {
				logger.fine("Valute so null");
				izbraneValute = vseValute;
			} else
				for (Integer sifraValute : parameters.getValute().getSifra())
					for (Valuta v : vseValute)
						if (v.getSifraValute() == sifraValute)
							izbraneValute.add(v);

			logger.fine("Zacenjam pripravo tecajnic. ");
			for (VrstaTecajnice vrsta : izbraneVrsteTecajnic) {
				for (Date d : izbraniDatumi) {

					TecajnicaType tecajnicaType = new TecajnicaType();
					tecajnicaType
							.setVrstaTecajnice(pretvoriVrstoTecajnic(vrsta));
					tecajnicaType.setDatumTecajnice(pretvoriDatum(d));
					List<TecajID> tecajiID = new ArrayList<TecajID>();
					for (Valuta v : izbraneValute) {
						TecajID tecajID = new TecajID();
						tecajID.setDatumTecajnice(d);
						tecajID.setSifraValute(v.getSifraValute());
						tecajID.setSifraVrsteTecajnice(vrsta
								.getSifraVrsteTecajnice());
						tecajiID.add(tecajID);
					}

					for (Tecaj t : tecajniceBean.vrniTecaje(tecajiID))
						tecajnicaType.getTecaj().add(pretvoriTecaj(t));

					if (!tecajnicaType.getTecaj().isEmpty())
						rezultat.getTecajnica().add(tecajnicaType);
				}
			}
			return rezultat;
		} catch (Exception e) {
			logger.severe("Napaka pri generiranju rezultata. " + e.getMessage());
			NapakaType faultInfo = new NapakaType();
			NapakaPriPovprasevanju napakaPriPovprasevanju = new NapakaPriPovprasevanju();
			napakaPriPovprasevanju
					.setSporocilo("Napaka pri generiranju rezultata.");
			napakaPriPovprasevanju.setPodrobnosti(e.toString());
			faultInfo.setNapakaPriPovprasevanju(napakaPriPovprasevanju);
			throw new VrniTecajniceNapaka("Napaka pri generiranju rezultata."
					+ e.getMessage(), faultInfo);
		}
	}

	public VrniValuteRezultat vrniValute(VrniValuteZahteva parameters)
			throws VrniValuteNapaka {
		try {
			logger.fine("Pripravljam odgovor operacije VrniValute. ");
			VrniValuteRezultat rezultat = new VrniValuteRezultat();

			if (parameters.getSifra().isEmpty()
					&& parameters.getOznaka().isEmpty()) {
				logger.finer("Pripravljam vse valute. ");
				for (Valuta valuta : valuteBean.vrniVseValute())
					rezultat.getValuta().add(pretvoriValuto(valuta));
			} else {
				logger.finer("Pripravljam valute glede na sifro valute. ");
				List<Valuta> valute = valuteBean.vrniValute(parameters
						.getSifra());
				for (Valuta v : valute)
					rezultat.getValuta().add(pretvoriValuto(v));

				logger.finer("Pripravljam valute glede na oznako valute. ");
				valute = valuteBean.vrniValuteZOznako(parameters.getOznaka());
				for (Valuta v : valute)
					rezultat.getValuta().add(pretvoriValuto(v));
			}

			return rezultat;
		} catch (Exception e) {
			logger.severe("Napaka pri generiranju rezultata. " + e.getMessage());
			NapakaType faultInfo = new NapakaType();
			NapakaPriPovprasevanju napakaPriPovprasevanju = new NapakaPriPovprasevanju();
			napakaPriPovprasevanju
					.setSporocilo("Napaka pri generiranju rezultata.");
			napakaPriPovprasevanju.setPodrobnosti(e.toString());
			faultInfo.setNapakaPriPovprasevanju(napakaPriPovprasevanju);
			throw new VrniValuteNapaka("Napaka pri generiranju rezultata."
					+ e.getMessage(), faultInfo);
		}
	}

	public VrniVrsteTecajnicRezultat vrniVrsteTecajnic(
			VrniVrsteTecajnicZahteva parameters) throws VrniVrsteTecajnicNapaka {
		try {
			logger.fine("Pripravljam odgovor operacije vrniVrsteTecajnic. ");
			VrniVrsteTecajnicRezultat rezultat = new VrniVrsteTecajnicRezultat();

			List<VrstaTecajnice> vrsteTecajnic = tecajniceBean
					.vrniVseVrsteTecajnic();

			if (parameters.getNazivVrsteTecajnice().isEmpty()
					&& parameters.getSifraVrsteTecajnice().isEmpty()) {
				logger.finer("Pripravljam vse vrste tecajnic. ");

				for (VrstaTecajnice vt : vrsteTecajnic)
					rezultat.getVrstaTecajnice().add(pretvoriVrstoTecajnic(vt));
			} else {

				for (VrstaTecajnice vt : vrsteTecajnic) {
					for (Integer sifra : parameters.getSifraVrsteTecajnice())
						if (vt.getSifraVrsteTecajnice() == sifra)
							rezultat.getVrstaTecajnice().add(
									pretvoriVrstoTecajnic(vt));

					for (String naziv : parameters.getNazivVrsteTecajnice())
						if (vt.getNazivVrsteTecajnice().equalsIgnoreCase(naziv))
							rezultat.getVrstaTecajnice().add(
									pretvoriVrstoTecajnic(vt));
				}
			}

			return rezultat;
		} catch (Exception e) {
			logger.severe("Napaka pri generiranju rezultata. " + e.getMessage());
			NapakaType faultInfo = new NapakaType();
			NapakaPriPovprasevanju napakaPriPovprasevanju = new NapakaPriPovprasevanju();
			napakaPriPovprasevanju
					.setSporocilo("Napaka pri generiranju rezultata.");
			napakaPriPovprasevanju.setPodrobnosti(e.toString());
			faultInfo.setNapakaPriPovprasevanju(napakaPriPovprasevanju);
			throw new VrniVrsteTecajnicNapaka(
					"Napaka pri generiranju rezultata." + e.getMessage(),
					faultInfo);
		}
	}

	private static ValutaType pretvoriValuto(Valuta valuta) {
		ValutaType valutaType = new ValutaType();

		DrzavaType drzava = new DrzavaType();
		drzava.setNaziv(valuta.getNazivDrzave());
		drzava.setOznaka(valuta.getOznakaDrzave());

		valutaType.setDrzava(drzava);
		valutaType.setNaziv(valuta.getNazivValute());
		valutaType.setOznaka(valuta.getOznakaValute());
		valutaType.setSifra(valuta.getSifraValute());

		return valutaType;
	}

	private static VrstaTecajniceType pretvoriVrstoTecajnic(
			VrstaTecajnice vrstaTecajnice) {
		VrstaTecajniceType vt = new VrstaTecajniceType();

		vt.setNaziv(vrstaTecajnice.getNazivVrsteTecajnice());
		vt.setSifra(vrstaTecajnice.getSifraVrsteTecajnice());

		return vt;
	}

	private TecajType pretvoriTecaj(Tecaj t) {
		TecajType tecajType = new TecajType();
		tecajType.setEnota(t.getEnotaTecaja().doubleValue());
		tecajType.setNakupniTecaj(t.getNakupniTecaj());
		tecajType.setProdajniTecaj(t.getProdajniTecaj());
		tecajType.setSrednjiTecaj(t.getSrednjiTecaj());
		tecajType.setValuta(pretvoriValuto(t.getValuta()));

		return tecajType;
	}

	private XMLGregorianCalendar pretvoriDatum(Date d)
			throws DatatypeConfigurationException {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(d);
		return DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
	}

}